#pragma once

#define DECLARE_MM_ENTRY(cmd) public: void On_##cmd(const sMirMessage& msg,const char* body);
#define IMPLEMENT_MM_ENTRY(cmd) void CLASS_GAME::On_##cmd(const sMirMessage& msg,const char* body)
#define ROUTINE_MM_ENTRY(cmd) case cmd: On_##cmd(msg,body); break;
#define IGNORE_MM_ENTRY(cmd) case cmd: break;
#define REDIRECT_MM_ENTRY(cmd) On_##cmd(msg,body);

class CNet : public CAsyncSocket
{
	DECLARE_DYNAMIC(CNet);
public:
	CNet()
		: m_RecvLen(0)
		, m_PacketIndex('1')
	{}
	virtual ~CNet(){}
	virtual void OnReceive(int nErrorCode)
	{
		int retval=Receive(m_RecvBuf+m_RecvLen,sizeof(m_RecvBuf)-m_RecvLen);
		m_RecvLen+=retval;
		m_RecvBuf[m_RecvLen]=static_cast<char>(0);
		char*start=m_RecvBuf;
		while((start=strchr(start,'*'))!=NULL)
		{
			Send(start,1);
			*start=' ';
			start++;
		}
		start=strchr(m_RecvBuf,'#');
		char*end;
		while(start!=NULL)
		{
			end=strchr(start+1,'!');
			if(end!=NULL)
			{
				*end=static_cast<char>(0);
				if(start[1]=='+')
				{
					OnResult(start+2);
				}
				else
				{
					sMirMessage msg;
					ZeroMemory(&msg,sizeof(msg));
					//char buf[0x10000];
					//ZeroMemory(buf,sizeof(buf));
					int dl=fnDecode6BitBufA(start+1,(char*)&msg,sizeof(msg));
					//sMirMessage*msg=static_cast<sMirMessage*>(static_cast<void*>(&buf[0]));
					OnMessage(msg,start+1+16);
				}
				start=strchr(end+1,'#');
			}
			else
				break;
		}
		if(start==NULL)
		{
			m_RecvLen=0;
			m_RecvBuf[0]=static_cast<char>(0);
		}
		else if(end==NULL)
		{
			m_RecvLen=(m_RecvBuf+m_RecvLen)-start;
			memcpy(m_RecvBuf,start,m_RecvLen);
		}
		CAsyncSocket::OnReceive(nErrorCode);
	}
	virtual void OnMessage(const sMirMessage& ,const char* )=0;
	virtual void OnResult(const char *)=0;

protected:
	char m_PacketIndex;

	char m_RecvBuf[0x10000];
	long m_RecvLen;

	virtual int fnEncode6BitBufA(unsigned char *pszSrc, char *pszDest, int nSrcLen, int nDestLen)=0;
	virtual int fnDecode6BitBufA(const char *pszSrc, char *pszDest, int nDestLen)=0;
public:
	int SendMsg( const sMirMessage& msg, const char* data=NULL )
	{
		char buf[0x1000];
		int retval=2;
		buf[0]='#';
		buf[1]=m_PacketIndex;

		m_PacketIndex++;
		if(m_PacketIndex>'9')m_PacketIndex='1';

		retval+=fnEncode6BitBufA((unsigned char*)&msg,&buf[retval],sizeof(sMirMessage),sizeof(buf));
		if(data)
			retval+=fnEncode6BitBufA((unsigned char*)data,&buf[retval],strlen(data),sizeof(buf)-retval);
		buf[retval]='!';
		retval++;
		buf[retval]=static_cast<char>(0);
		Send(buf,retval);
		return 0;
	}
	int SendMsg( WORD wCmd, DWORD dwFlag=0, WORD w1=0, WORD w2=0, WORD w3=0, const char* data=NULL)
	{
		sMirMessage msg;
		msg.dwFlag=dwFlag;
		msg.wCmd=wCmd;
		msg.w1=w1;
		msg.w2=w2;
		msg.w3=w3;

		char buf[0x1000];
		int retval=2;
		buf[0]='#';
		buf[1]=m_PacketIndex;

		m_PacketIndex++;
		if(m_PacketIndex>'9')m_PacketIndex='1';

		retval+=fnEncode6BitBufA((unsigned char*)&msg,&buf[retval],sizeof(sMirMessage),sizeof(buf));
		if(data)
			retval+=fnEncode6BitBufA((unsigned char*)data,&buf[retval],strlen(data),sizeof(buf)-retval);
		buf[retval]='!';
		retval++;
		buf[retval]=static_cast<char>(0);
		Send(buf,retval);
		return 0;
	}
public:
	static void SplitString(const char* str, const char* split, std::vector<std::string>& sl)
	{
		const boost::regex reSplite(split,boost::regbase::normal|boost::regbase::icase);
		boost::regex_split(std::back_inserter(sl),std::string(str),reSplite);
	}
};